Skip to content

feat(sdk): add .NET SDK over libmoss (closes #431) - #460

Open
Adityacrypto-del wants to merge 3 commits into
usemoss:mainfrom
Adityacrypto-del:sdk-dotnet
Open

feat(sdk): add .NET SDK over libmoss (closes #431)#460
Adityacrypto-del wants to merge 3 commits into
usemoss:mainfrom
Adityacrypto-del:sdk-dotnet

Conversation

@Adityacrypto-del

@Adityacrypto-del Adityacrypto-del commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Pull Request Checklist

  • I have read the CONTRIBUTING guide.
  • I have updated the documentation (if applicable). — added sdks/dotnet/README.md
  • My code follows the style guidelines of this project.
  • I have performed a self-review of my own code.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.

Description

Adds a .NET SDK for Moss under sdks/dotnet/, following the same two-layer
structure as the existing SDKs: an idiomatic async client (src/Moss) over a
P/Invoke interop layer (src/Moss/Interop) that binds the native libmoss
C ABI — the same surface the Go bindings use via cgo.

Covers the issue scope: index management (create/get/list/delete), document
operations (add/delete/get), local runtime (load/unload/refresh), hybrid
search (QueryAsync), and metadata filtering. Failures surface as
MossException carrying the native status code and moss_last_error message.

  • Target framework: net8.0 (async, Task-based API)
  • 18 unit tests covering models, argument validation, UTF-8 marshaling, native
    buffer packing, and ABI struct layouts — all run without the native library
  • README with quickstart, architecture, and build/test instructions

Note: the compiled libmoss runtime is required only to run queries, not to
build or unit-test the SDK.

Fixes #431

Type of Change

  • New feature (non-breaking change which adds functionality)

Review in cubic

@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown

Codex review

The new .NET SDK structure is coherent, but a few contract mismatches will make important first-run and custom-embedding workflows unreliable. The biggest risks are around async mutation completion semantics and model selection for precomputed embeddings.

{
RequireName(name);
DocumentInfo[] snapshot = SnapshotDocs(docs);
return RunAsync(() => _native.CreateIndex(name, snapshot, modelId), cancellationToken);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BLOCKING CreateIndexAsync, AddDocsAsync, and DeleteDocsAsync return the native mutation result directly, but the SDK contract for these mutation calls is to poll the async job until completion before returning; MutationResult is documented as the result when the mutation job completes. The README then immediately calls LoadIndexAsync, so callers can race a still-building index.

return RunAsync(() => _native.CreateIndex(name, snapshot, modelId), cancellationToken);

Fix by polling GetJobStatus until completed/failed before resolving these mutation tasks, or rename/document them as enqueue-only and update the quick start to wait for the job. (pkg.go.dev)

using var arena = new NativeArena();
IntPtr docsPtr = BuildDocuments(arena, docs);
Check(NativeMethods.moss_client_create_index(
_handle, arena.String(name), docsPtr, (nuint)docs.Count, arena.String(modelId), out IntPtr outPtr));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BLOCKING Custom-embedding index creation is not handled: documents can carry Embedding, but this path forwards a null modelId unchanged and never enforces the all-or-none embedding rule. The existing SDK behavior defaults ModelID to "custom" when documents already have embeddings and rejects mixed batches.

_handle, arena.String(name), docsPtr, (nuint)docs.Count, arena.String(modelId), out IntPtr outPtr)

Fix by detecting embeddings after SnapshotDocs: if any document has an embedding, require all documents to have one and set modelId ??= "custom" before calling native. (pkg.go.dev)

Comment thread sdks/dotnet/README.md
(`libmoss.so` on Linux, `libmoss.dylib` on macOS, `moss.dll` on Windows). It
must be discoverable at runtime — on the standard library search path, next to
your application, or via `NativeLibrary` resolution. Building and unit-testing
the SDK does **not** require the native library; only running queries does.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONSIDER The runtime requirement is understated. MossClient calls moss_client_new in its constructor, so any valid client creation or management call requires the native library, not only queries.

Building and unit-testing the SDK does **not** require the native library; only running queries does.

Fix the docs to say libmoss is required whenever an application constructs/uses MossClient, or lazy-initialize native runtime only for local query operations if management APIs are meant to work without it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SDK: .NET client for Moss

2 participants